package com.voip.mySipPhone;



import javax.sip.*;
import javax.sip.address.AddressFactory;
import javax.sip.address.Hop;
import javax.sip.address.Router;
import javax.sip.header.CSeqHeader;
import javax.sip.header.HeaderFactory;
import javax.sip.message.MessageFactory;
import javax.sip.message.Request;
import javax.sip.message.Response;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.net.InetAddress;
import java.util.ListIterator;
import java.util.Properties;
import java.util.TooManyListenersException;

/**
 * Created by RXJ on 2018/1/25.
 */
public class SipPhone implements SipListener ,Router{

    public SipPhone listener;
    public String registerHost ="192.168.1.218";
    public int registerPort = 5060;
    public String localHost ;
    public int localPort ;

    public String username = "814";
    public String password = "123456";
    public String callID;


    public SipFactory sipFactory;
    public SipStack sipStack;
    public SipProvider sipProvider;
    public HeaderFactory headerFactory;
    public AddressFactory addressFactory;
    public MessageFactory messageFactory;

    public SipPhone(String host ,int port) throws PeerUnavailableException, InvalidArgumentException, TransportNotSupportedException, ObjectInUseException, TooManyListenersException {
        setLocalHost(host);
        setLocalPost(port);
        sipFactory = SipFactory.getInstance();
        sipFactory.setPathName("gov.nist");

        Properties properties = new Properties();
        properties.setProperty("javax.sip.STACK_NAME", "SipPhone");
        properties.setProperty("javax.sip.IP_ADDRESS",localHost);
        //properties.setProperty("javax.sip.ROUTER_PATH", "com.voip.mySipPhone.SipPhone");
        properties.setProperty(
                "gov.nist.javax.sip.CACHE_CLIENT_CONNECTIONS", "false");
        properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "32");
        properties.setProperty("gov.nist.javax.sip.SERVER_LOG", "SipPhone.txt");
        properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", "SipPhoneDebugLog.log");

        sipStack = sipFactory.createSipStack(properties);

        headerFactory = sipFactory.createHeaderFactory();
        addressFactory = sipFactory.createAddressFactory();
        messageFactory = sipFactory.createMessageFactory();

        ListeningPoint tcp1 = sipStack.createListeningPoint(port, "tcp");
        ListeningPoint udp1 = sipStack.createListeningPoint(port, "udp");

        sipProvider =  sipStack.createSipProvider(tcp1);
        sipProvider.addSipListener(this);
        sipProvider =  sipStack.createSipProvider(udp1);
        sipProvider.addSipListener(this);

        callID = System.currentTimeMillis() + "@" + localHost;

        if(listener == null){
            listener=this;
        }

    }

    @Override
    public void processRequest(RequestEvent requestEvent) {
        Request request = requestEvent.getRequest();

        if (null == request) {
            System.out.println("processRequest request is null.");
            return;
        }
        if (Request.BYE.equalsIgnoreCase(request.getMethod())) {
            System.out.println("Request Bye :\n"+ request);
        }else{
            System.out.println(requestEvent);
        }
    }

    @Override
    public void processResponse(ResponseEvent responseEvent) {
        Response response = responseEvent.getResponse();

        String method = ((CSeqHeader) response.getHeader(CSeqHeader.NAME)).getMethod();

        if (response.getStatusCode() == Response.OK)  {
            if (method.equals(Request.REGISTER)) {
              //  setRegistered(true);
            }
        }

        if (response.getStatusCode() == 401) {
            //   handleAuthorization(responseEvent, response, method);
        } else if (response.getStatusCode() == 407) {
            //  handleProxyAuthorization(responseEvent, response, method);
        }
    }

    @Override
    public void processTimeout(TimeoutEvent timeoutEvent) {
        System.out.println("processTimeout:\n"+timeoutEvent);
    }

    @Override
    public void processIOException(IOExceptionEvent ioExceptionEvent) {
        System.out.println("processIOException:\n"+ioExceptionEvent);
    }

    @Override
    public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) {
        System.out.println("processTransactionTerminated:\n"+transactionTerminatedEvent);
    }

    @Override
    public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) {
        System.out.println("processDialogTerminated:\n"+dialogTerminatedEvent);
    }

    public void setLocalHost(String host){
        this.localHost = host;
    }
    public void setLocalPost(int port){
        this.localPort = port;
    }

    public static void main(String args[]) throws Exception {
        int pid =0;
        RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
        String name = runtime.getName();
        System.out.println("当前进程的标识为："+name);
        int index = name.indexOf("@");
        if (index != -1) {
            pid = Integer.parseInt(name.substring(0, index));
            System.out.println("当前进程的PID为："+pid);
        }

        try {
            int port = pid;
            String ip = InetAddress.getLocalHost().getHostAddress();
            System.out.println("--port = " + port + "\n--ip = " + ip);
            SipPhone sipPhone = new SipPhone(ip,port);
        } catch (PeerUnavailableException e) {
            e.printStackTrace();
        } catch (InvalidArgumentException e) {
            e.printStackTrace();
        } catch (TransportNotSupportedException e) {
            e.printStackTrace();
        } catch (ObjectInUseException e) {
            e.printStackTrace();
        } catch (TooManyListenersException e) {
            e.printStackTrace();
        }
    }

    @Override
    public Hop getOutboundProxy() {
        return null;
    }

    @Override
    public ListIterator getNextHops(Request request) {
        return null;
    }

    @Override
    public Hop getNextHop(Request request) throws SipException {
        return null;
    }
}
